package cli

import (
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	"gitee.com/dark.H/go-remote-repl/datas"
	"gitee.com/dark.H/go-remote-repl/lpc"
	"gitee.com/dark.H/go-remote-repl/remote"
	"github.com/c-bata/go-prompt"
	"github.com/google/uuid"
	"golang.org/x/crypto/ssh"
)

func APIParse(apiserver ...net.Conn) {
	if _, out := ArrayExists(os.Args, "apihelp"); out {
		for _, a := range []string{"apidep", "apicli", "apiserv"} {
			fmt.Println(datas.Green("oper:  ", a))
		}
		os.Exit(0)
	}

	APIExtention(apiserver...)

}

func APIExtention(apiserver ...net.Conn) {
	if nargs, out := ArrayExists(os.Args, "api"); out {
		os.Args = nargs
		flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
		TuiRun(apiserver...)
		os.Exit(0)
	}

	// if nargs, out := ArrayExists(os.Args, "apidep"); out {
	// 	os.Args = nargs
	// 	var remoteAPI string
	// 	var remove bool
	// 	flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	// 	flag.StringVar(&remoteAPI, "t", "", "target, connect remote api's ip/host")
	// 	flag.BoolVar(&remove, "D", false, "remove remote's deployed file if exists")
	// 	flag.Parse()
	// 	if remoteAPI != "" {
	// 		if !strings.Contains(remoteAPI, ":") {
	// 			remoteAPI += ":22"
	// 		}
	// 		if name, auth_info := remote.Ssh("ssh://"+remoteAPI).SshSync(os.Args[0], remove, func(name string, sshcli *ssh.Client) {
	// 			remote.RunByClient(sshcli, "chmod +x "+name+"&& "+name+" apiserv -on -D")
	// 		}); name != "" && auth_info == "" {
	// 			log.Fatal(name)
	// 		}
	// 	}
	// 	os.Exit(0)
	// }
	// if nargs, out := ArrayExists(os.Args, "apicli"); out {
	// 	os.Args = nargs
	// 	var remoteAPI string
	// 	var syncFile string
	// 	var sshCmd string
	// 	var opData bool
	// 	flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	// 	flag.StringVar(&syncFile, "sync", "", "sync file to remote's tmp !")
	// 	flag.StringVar(&sshCmd, "c", "", "run remote's shell by ssh !")
	// 	flag.BoolVar(&opData, "db", false, "cli controll api's db!")
	// 	flag.StringVar(&remoteAPI, "t", "", "target, connect remote api's ip/host")
	// 	flag.Parse()
	// 	if remoteAPI != "" {
	// 		if !strings.Contains(remoteAPI, ":") {
	// 			remoteAPI += ":65531"
	// 		}

	// 		if sshCmd != "" {
	// 			fmt.Println(remote.Ssh("ssh://" + remoteAPI).SshShell(sshCmd))
	// 		} else {
	// 			ClientConnect(remoteAPI)
	// 		}
	// 	}
	// 	os.Exit(0)
	// } else {
	if nargs, out := ArrayExists(os.Args, "apiserv"); out {
		var startLocal bool
		var startOuter bool
		var start bool
		var stop bool

		background := false
		os.Args = nargs
		startOuter = true
		flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)

		flag.BoolVar(&startLocal, "on", false, "Start/Stop Local API sock server in env[tmppath]'s localCentry.sock")
		flag.BoolVar(&start, "start", false, "start service")
		flag.BoolVar(&stop, "stop", false, "start service")
		flag.BoolVar(&background, "D", false, "Run in daemon")

		flag.Parse()
		if background {
			RunDaemon()
			os.Exit(0)
		}
		if start {
			if !lpc.IfOuterStart() {
				go StartOuterAPIServer()
				// os.Exit(0)
			} else {
				fmt.Println("first ... kill old !!!!")
				lpc.KillAPI()
				time.Sleep(1 * time.Second)
				go StartOuterAPIServer()
			}
			if !lpc.IfLocalStart() {
				ln, err := lpc.UnixListener()
				if err != nil {
					log.Fatal("unix start err:", err)
				}
				RunningAPIListener(ln)
			}
			os.Exit(0)
		}
		if stop {
			lpc.KillAPI()
			os.Exit(0)
		}
		StartServerAll(startLocal, startOuter)
		os.Exit(0)
	}

	flag.Parse()

}

func TuiRun(apiserver ...net.Conn) {
	// var golangOldFlagJson string
	var remoteHost string
	flag.StringVar(&remoteHost, "t", "", "target, connect remote api's ip/host")
	flag.Parse()
	switch datas.Tui.Select("menu Top", "client connect", "deploy manager") {
	case "client connect":
		if remoteHost == "" {
			remoteHost = "localhost:65531"
		}
		if !strings.Contains(remoteHost, ":") {
			remoteHost += ":65531"
		}
		ClientConnect(remoteHost)

	case "deploy manager":

		// switch datas.Tui.Select("choose a file to deploy self to server \n/just upload other file to server/\nDeploy RPC Service:", "Deploy Self", "Upload Other File", "Deploy RPC Service") {
		// case "Deploy RPC Service":
		if remoteHost == "" {
			remoteHost = datas.Tui.Input("host >", datas.Datas{
				"localhost": "local host",
				"192.168.":  "local net ",
			})
		}
		if remoteHost != "" {
			if !strings.Contains(remoteHost, ":") {
				remoteHost += ":22"
			}
			remove := false
			switch datas.Tui.Select("if remove exists service file?", "control", "update", "remove", "ssh") {
			case "ssh":
				remote.Ssh("ssh://"+remoteHost).SshShell("ls /tmp/????????-????-????-????-????????????*", func(sshcli *ssh.Client) {
					for {
						out := prompt.Input("ssh shell>>", func(d prompt.Document) (o []prompt.Suggest) { return })
						if out == "exit" {
							break
						}
						remote.RunByClient(sshcli, out)
					}
				})
			case "remove":
				remote.Ssh("ssh://"+remoteHost).SshShell("ls /tmp/????????-????-????-????-????????????*", func(sshcli *ssh.Client) {
					U := uuid.NewMD5(uuid.UUID{}, []byte(os.Args[0]))
					name := filepath.Join("/tmp", U.String())
					remote.RunByClient(sshcli, "chmod +x "+name+"&& "+name+" apiserv -stop -D")
					remote.RunByClient(sshcli, "rm /tmp/????????-????-????-????-????????????*")
				})
				os.Exit(0)
			case "update":
				remove = true
			}
			if name, auth_info := remote.Ssh("ssh://"+remoteHost).SshSync(os.Args[0], remove, func(name string, sshcli *ssh.Client) {
				switch datas.Tui.Select("start/stop", "start", "stop") {
				case "start":
					remote.RunByClient(sshcli, "chmod +x "+name+"&& "+name+" apiserv -start -D")
				case "stop":
					remote.RunByClient(sshcli, "chmod +x "+name+"&& "+name+" apiserv -stop -D")
				}
			}); name != "" && auth_info == "" {
				log.Fatal(name)
			}
		}

		// }

	}
}
